<?php

/**
 * Simple Event engine
 *
 * Mилeнькaя_KOШEЧK@ 80661470860
 * 0676319496
 *
 */
require("components/FComponent.frodo.php");
require("components/FButton.frodo.php");
require("components/FLabel.frodo.php");
require("components/FInput.frodo.php");


class Frodo{
	
	private $formStarted=false;
	private $formEnded=false;
	public $internalCode;
	private $__name;
	public $restored=false;
	private $__components=array();
	const sessName="______FrodoApplication";
	private $html=false;
	private $xml;
	
	public function __construct()
	{
		
	}
	
	public function __addComponent($c){
		array_push($this->__components,$c);
		//var_dump($this->__components);
	}
	
	private function parseHTML()
	{
		$html=file_get_contents($this->path);
		$xml=DOMDocument::loadXML($this->stripPHP($html));
		$script=$xml->createElement('script');
		$script->setAttribute('src','./js/frodo.js');
		$xml->getElementsByTagName('head')->item(0)->appendChild($script);
		$form=$xml->createElement("form");
		$form->setAttribute("action","");
		$form->setAttribute("method","post");
		$form->setAttribute("id","___sender_form");
		$code=$xml->createElement("input");
		$code->setAttribute("type","hidden");
		$code->setAttribute("name","__INTERNALCODE_");
		$code->setAttribute("value",$this->internalCode);
		$form->appendChild($code);
		$sender=$xml->createElement("input");
		$sender->setAttribute("type","hidden");
		$sender->setAttribute("name","___send_element");
		$sender->setAttribute("id","___send_element");
		$sender->setAttribute("value","");
		$script=$xml->createElement("script");
		$script->setAttribute("src",$_SERVER['DOCUMENT_ROOT']."/js/Frodo.js");
		$form->appendChild($sender);
		$body=$xml->getElementsByTagName("body")->item(0);
		while($tag=$body->getElementsByTagName("*")->item(0)){
			$form->appendChild($tag);
		}
		$body->appendChild($form);
		$items=$xml->getElementsByTagNameNS("http://www.cozzy.net/frodo/","*");
		while($item=$items->item(0)){
			$class = "F".ucfirst(strtolower($item->localName));
			if(!$name=$item->getAttribute("name")){
				echo "every element must have name";
				exit();
			}
			if(!isset($this->$name))$this->$name = new $class($this,$item);
			$child=$this->$name->getElementXml($xml,$item);
			$item->parentNode->replaceChild($child,$item);
		}
		$xml->normalize();
		$this->xml=$xml;
	}
	
	public function prepareHTML(){
		$this->html=$this->xml->saveXML();
	}
	
	private function stripPHP($html){
		$startPos=strpos($html,"<?php");
		do{
			$endpos=strpos($html,"?>")+2;
			if(!$endpos) break;
			$repl=substr($html,$startPos,$endpos-$startPos);
			$html=str_replace($repl,"",$html);
			$startPos=strpos($html,"<?php");
		}while ($startPos=strpos($html,"<?php"));
		return $html;
	}
	
	public static function create($appName)
	{
		session_start();
		$newApp= new $appName();
		$newApp->__name=$appName;
		$newApp->internalCode=md5(rand(0,9999999));
		$oldApp=@$_SESSION[Frodo::sessName]; 
		//echo "restored app :: ->".$_SESSION[Frodo::sessName]->internalCode."<br />";
		if(!isset($oldApp->internalCode)||(@$_POST["__INTERNALCODE_"]!=$oldApp->internalCode)){
			$app=$newApp;
			$_SESSION[Frodo::sessName]->restored=true;
		}else{
			$app=$oldApp;
		}
		//echo "current app".$app->internalCode."<br />";
		$app->parseHTML();
		if(method_exists($app,"main"))$app->main();
		$app->catchVals();
		$app->dispatchEvents();
		$app->parseHTML();
		$app->prepareHTML();
		echo $app->html;
		//return $app;
		exit();
	}
	
	public function __destruct()
	{
		if(get_class($this)==$this->__name&&$this->restored!=true){
			$_SESSION[Frodo::sessName]=$this;
			session_commit();
		}
	}
	
	public function formStart(){
		if($this->formEnded) return false;
		printf("<form action=\"#\" method=\"post\">\n");
		printf("\t<input type=\"hidden\" name=\"__INTERNALCODE_\" value=\"%s\" />\n",
		$this->internalCode);
		$this->formStarted=true;
	}
	
	public function formEnd()
	{
		if(!$this->formStarted) return false;
		printf("</form>");
		$this->formEnded=true;
	}
	
	public function clearForms()
	{
		$this->formEnded=false;
		$this->formStarted=false;
	}
	
	public function catchVals()
	{
		foreach ($this as $prop=>$val){	
			if(isset($_POST[$prop])&&method_exists($val,"catchPostedValue")){
				$val->catchPostedValue($_POST[$prop]);
			}
		}
	}
	
	public function dispatchEvents()
	{
		//var_dump($_POST);
		foreach ($this as $prop=>$val){	
			if(method_exists($val,"dispatchEvent")){
				$val->dispatchEvent();
				//$this->parseHTML();
			}
		}
	}
	
	public function onPageInit()
	{
		// TODO: override in children
	}
	
}


?>